home *** CD-ROM | disk | FTP | other *** search
- SUBROUTINE DHSEQR( JOB, COMPZ, N, ILO, IHI, H, LDH, WR, WI, Z,
- $ LDZ, WORK, LWORK, INFO )
- *
- * -- LAPACK routine (version 2.0) --
- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
- * Courant Institute, Argonne National Lab, and Rice University
- * September 30, 1994
- *
- * .. Scalar Arguments ..
- CHARACTER COMPZ, JOB
- INTEGER IHI, ILO, INFO, LDH, LDZ, LWORK, N
- * ..
- * .. Array Arguments ..
- DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ),
- $ Z( LDZ, * )
- * ..
- *
- * Purpose
- * =======
- *
- * DHSEQR computes the eigenvalues of a real upper Hessenberg matrix H
- * and, optionally, the matrices T and Z from the Schur decomposition
- * H = Z T Z**T, where T is an upper quasi-triangular matrix (the Schur
- * form), and Z is the orthogonal matrix of Schur vectors.
- *
- * Optionally Z may be postmultiplied into an input orthogonal matrix Q,
- * so that this routine can give the Schur factorization of a matrix A
- * which has been reduced to the Hessenberg form H by the orthogonal
- * matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T.
- *
- * Arguments
- * =========
- *
- * JOB (input) CHARACTER*1
- * = 'E': compute eigenvalues only;
- * = 'S': compute eigenvalues and the Schur form T.
- *
- * COMPZ (input) CHARACTER*1
- * = 'N': no Schur vectors are computed;
- * = 'I': Z is initialized to the unit matrix and the matrix Z
- * of Schur vectors of H is returned;
- * = 'V': Z must contain an orthogonal matrix Q on entry, and
- * the product Q*Z is returned.
- *
- * N (input) INTEGER
- * The order of the matrix H. N >= 0.
- *
- * ILO (input) INTEGER
- * IHI (input) INTEGER
- * It is assumed that H is already upper triangular in rows
- * and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally
- * set by a previous call to DGEBAL, and then passed to SGEHRD
- * when the matrix output by DGEBAL is reduced to Hessenberg
- * form. Otherwise ILO and IHI should be set to 1 and N
- * respectively.
- * 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.
- *
- * H (input/output) DOUBLE PRECISION array, dimension (LDH,N)
- * On entry, the upper Hessenberg matrix H.
- * On exit, if JOB = 'S', H contains the upper quasi-triangular
- * matrix T from the Schur decomposition (the Schur form);
- * 2-by-2 diagonal blocks (corresponding to complex conjugate
- * pairs of eigenvalues) are returned in standard form, with
- * H(i,i) = H(i+1,i+1) and H(i+1,i)*H(i,i+1) < 0. If JOB = 'E',
- * the contents of H are unspecified on exit.
- *
- * LDH (input) INTEGER
- * The leading dimension of the array H. LDH >= max(1,N).
- *
- * WR (output) DOUBLE PRECISION array, dimension (N)
- * WI (output) DOUBLE PRECISION array, dimension (N)
- * The real and imaginary parts, respectively, of the computed
- * eigenvalues. If two eigenvalues are computed as a complex
- * conjugate pair, they are stored in consecutive elements of
- * WR and WI, say the i-th and (i+1)th, with WI(i) > 0 and
- * WI(i+1) < 0. If JOB = 'S', the eigenvalues are stored in the
- * same order as on the diagonal of the Schur form returned in
- * H, with WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2
- * diagonal block, WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and
- * WI(i+1) = -WI(i).
- *
- * Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
- * If COMPZ = 'N': Z is not referenced.
- * If COMPZ = 'I': on entry, Z need not be set, and on exit, Z
- * contains the orthogonal matrix Z of the Schur vectors of H.
- * If COMPZ = 'V': on entry Z must contain an N-by-N matrix Q,
- * which is assumed to be equal to the unit matrix except for
- * the submatrix Z(ILO:IHI,ILO:IHI); on exit Z contains Q*Z.
- * Normally Q is the orthogonal matrix generated by DORGHR after
- * the call to DGEHRD which formed the Hessenberg matrix H.
- *
- * LDZ (input) INTEGER
- * The leading dimension of the array Z.
- * LDZ >= max(1,N) if COMPZ = 'I' or 'V'; LDZ >= 1 otherwise.
- *
- * WORK (workspace) DOUBLE PRECISION array, dimension (N)
- *
- * LWORK (input) INTEGER
- * This argument is currently redundant.
- *
- * INFO (output) INTEGER
- * = 0: successful exit
- * < 0: if INFO = -i, the i-th argument had an illegal value
- * > 0: if INFO = i, DHSEQR failed to compute all of the
- * eigenvalues in a total of 30*(IHI-ILO+1) iterations;
- * elements 1:ilo-1 and i+1:n of WR and WI contain those
- * eigenvalues which have been successfully computed.
- *
- * =====================================================================
- *
- * .. Parameters ..
- DOUBLE PRECISION ZERO, ONE, TWO
- PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )
- DOUBLE PRECISION CONST
- PARAMETER ( CONST = 1.5D+0 )
- INTEGER NSMAX, LDS
- PARAMETER ( NSMAX = 15, LDS = NSMAX )
- * ..
- * .. Local Scalars ..
- LOGICAL INITZ, WANTT, WANTZ
- INTEGER I, I1, I2, IERR, II, ITEMP, ITN, ITS, J, K, L,
- $ MAXB, NH, NR, NS, NV
- DOUBLE PRECISION ABSW, OVFL, SMLNUM, TAU, TEMP, TST1, ULP, UNFL
- * ..
- * .. Local Arrays ..
- DOUBLE PRECISION S( LDS, NSMAX ), V( NSMAX+1 ), VV( NSMAX+1 )
- * ..
- * .. External Functions ..
- LOGICAL LSAME
- INTEGER IDAMAX, ILAENV
- DOUBLE PRECISION DLAMCH, DLANHS, DLAPY2
- EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANHS, DLAPY2
- * ..
- * .. External Subroutines ..
- EXTERNAL DCOPY, DGEMV, DLABAD, DLACPY, DLAHQR, DLARFG,
- $ DLARFX, DLASET, DSCAL, XERBLA
- * ..
- * .. Intrinsic Functions ..
- INTRINSIC ABS, MAX, MIN
- * ..
- * .. Executable Statements ..
- *
- * Decode and test the input parameters
- *
- WANTT = LSAME( JOB, 'S' )
- INITZ = LSAME( COMPZ, 'I' )
- WANTZ = INITZ .OR. LSAME( COMPZ, 'V' )
- *
- INFO = 0
- IF( .NOT.LSAME( JOB, 'E' ) .AND. .NOT.WANTT ) THEN
- INFO = -1
- ELSE IF( .NOT.LSAME( COMPZ, 'N' ) .AND. .NOT.WANTZ ) THEN
- INFO = -2
- ELSE IF( N.LT.0 ) THEN
- INFO = -3
- ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN
- INFO = -4
- ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN
- INFO = -5
- ELSE IF( LDH.LT.MAX( 1, N ) ) THEN
- INFO = -7
- ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. LDZ.LT.MAX( 1, N ) ) THEN
- INFO = -11
- END IF
- IF( INFO.NE.0 ) THEN
- CALL XERBLA( 'DHSEQR', -INFO )
- RETURN
- END IF
- *
- * Initialize Z, if necessary
- *
- IF( INITZ )
- $ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )
- *
- * Store the eigenvalues isolated by DGEBAL.
- *
- DO 10 I = 1, ILO - 1
- WR( I ) = H( I, I )
- WI( I ) = ZERO
- 10 CONTINUE
- DO 20 I = IHI + 1, N
- WR( I ) = H( I, I )
- WI( I ) = ZERO
- 20 CONTINUE
- *
- * Quick return if possible.
- *
- IF( N.EQ.0 )
- $ RETURN
- IF( ILO.EQ.IHI ) THEN
- WR( ILO ) = H( ILO, ILO )
- WI( ILO ) = ZERO
- RETURN
- END IF
- *
- * Set rows and columns ILO to IHI to zero below the first
- * subdiagonal.
- *
- DO 40 J = ILO, IHI - 2
- DO 30 I = J + 2, N
- H( I, J ) = ZERO
- 30 CONTINUE
- 40 CONTINUE
- NH = IHI - ILO + 1
- *
- * Determine the order of the multi-shift QR algorithm to be used.
- *
- NS = ILAENV( 4, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )
- MAXB = ILAENV( 8, 'DHSEQR', JOB // COMPZ, N, ILO, IHI, -1 )
- IF( NS.LE.2 .OR. NS.GT.NH .OR. MAXB.GE.NH ) THEN
- *
- * Use the standard double-shift algorithm
- *
- CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO,
- $ IHI, Z, LDZ, INFO )
- RETURN
- END IF
- MAXB = MAX( 3, MAXB )
- NS = MIN( NS, MAXB, NSMAX )
- *
- * Now 2 < NS <= MAXB < NH.
- *
- * Set machine-dependent constants for the stopping criterion.
- * If norm(H) <= sqrt(OVFL), overflow should not occur.
- *
- UNFL = DLAMCH( 'Safe minimum' )
- OVFL = ONE / UNFL
- CALL DLABAD( UNFL, OVFL )
- ULP = DLAMCH( 'Precision' )
- SMLNUM = UNFL*( NH / ULP )
- *
- * I1 and I2 are the indices of the first row and last column of H
- * to which transformations must be applied. If eigenvalues only are
- * being computed, I1 and I2 are set inside the main loop.
- *
- IF( WANTT ) THEN
- I1 = 1
- I2 = N
- END IF
- *
- * ITN is the total number of multiple-shift QR iterations allowed.
- *
- ITN = 30*NH
- *
- * The main loop begins here. I is the loop index and decreases from
- * IHI to ILO in steps of at most MAXB. Each iteration of the loop
- * works with the active submatrix in rows and columns L to I.
- * Eigenvalues I+1 to IHI have already converged. Either L = ILO or
- * H(L,L-1) is negligible so that the matrix splits.
- *
- I = IHI
- 50 CONTINUE
- L = ILO
- IF( I.LT.ILO )
- $ GO TO 170
- *
- * Perform multiple-shift QR iterations on rows and columns ILO to I
- * until a submatrix of order at most MAXB splits off at the bottom
- * because a subdiagonal element has become negligible.
- *
- DO 150 ITS = 0, ITN
- *
- * Look for a single small subdiagonal element.
- *
- DO 60 K = I, L + 1, -1
- TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )
- IF( TST1.EQ.ZERO )
- $ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )
- IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )
- $ GO TO 70
- 60 CONTINUE
- 70 CONTINUE
- L = K
- IF( L.GT.ILO ) THEN
- *
- * H(L,L-1) is negligible.
- *
- H( L, L-1 ) = ZERO
- END IF
- *
- * Exit from loop if a submatrix of order <= MAXB has split off.
- *
- IF( L.GE.I-MAXB+1 )
- $ GO TO 160
- *
- * Now the active submatrix is in rows and columns L to I. If
- * eigenvalues only are being computed, only the active submatrix
- * need be transformed.
- *
- IF( .NOT.WANTT ) THEN
- I1 = L
- I2 = I
- END IF
- *
- IF( ITS.EQ.20 .OR. ITS.EQ.30 ) THEN
- *
- * Exceptional shifts.
- *
- DO 80 II = I - NS + 1, I
- WR( II ) = CONST*( ABS( H( II, II-1 ) )+
- $ ABS( H( II, II ) ) )
- WI( II ) = ZERO
- 80 CONTINUE
- ELSE
- *
- * Use eigenvalues of trailing submatrix of order NS as shifts.
- *
- CALL DLACPY( 'Full', NS, NS, H( I-NS+1, I-NS+1 ), LDH, S,
- $ LDS )
- CALL DLAHQR( .FALSE., .FALSE., NS, 1, NS, S, LDS,
- $ WR( I-NS+1 ), WI( I-NS+1 ), 1, NS, Z, LDZ,
- $ IERR )
- IF( IERR.GT.0 ) THEN
- *
- * If DLAHQR failed to compute all NS eigenvalues, use the
- * unconverged diagonal elements as the remaining shifts.
- *
- DO 90 II = 1, IERR
- WR( I-NS+II ) = S( II, II )
- WI( I-NS+II ) = ZERO
- 90 CONTINUE
- END IF
- END IF
- *
- * Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns))
- * where G is the Hessenberg submatrix H(L:I,L:I) and w is
- * the vector of shifts (stored in WR and WI). The result is
- * stored in the local array V.
- *
- V( 1 ) = ONE
- DO 100 II = 2, NS + 1
- V( II ) = ZERO
- 100 CONTINUE
- NV = 1
- DO 120 J = I - NS + 1, I
- IF( WI( J ).GE.ZERO ) THEN
- IF( WI( J ).EQ.ZERO ) THEN
- *
- * real shift
- *
- CALL DCOPY( NV+1, V, 1, VV, 1 )
- CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),
- $ LDH, VV, 1, -WR( J ), V, 1 )
- NV = NV + 1
- ELSE IF( WI( J ).GT.ZERO ) THEN
- *
- * complex conjugate pair of shifts
- *
- CALL DCOPY( NV+1, V, 1, VV, 1 )
- CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ),
- $ LDH, V, 1, -TWO*WR( J ), VV, 1 )
- ITEMP = IDAMAX( NV+1, VV, 1 )
- TEMP = ONE / MAX( ABS( VV( ITEMP ) ), SMLNUM )
- CALL DSCAL( NV+1, TEMP, VV, 1 )
- ABSW = DLAPY2( WR( J ), WI( J ) )
- TEMP = ( TEMP*ABSW )*ABSW
- CALL DGEMV( 'No transpose', NV+2, NV+1, ONE,
- $ H( L, L ), LDH, VV, 1, TEMP, V, 1 )
- NV = NV + 2
- END IF
- *
- * Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero,
- * reset it to the unit vector.
- *
- ITEMP = IDAMAX( NV, V, 1 )
- TEMP = ABS( V( ITEMP ) )
- IF( TEMP.EQ.ZERO ) THEN
- V( 1 ) = ONE
- DO 110 II = 2, NV
- V( II ) = ZERO
- 110 CONTINUE
- ELSE
- TEMP = MAX( TEMP, SMLNUM )
- CALL DSCAL( NV, ONE / TEMP, V, 1 )
- END IF
- END IF
- 120 CONTINUE
- *
- * Multiple-shift QR step
- *
- DO 140 K = L, I - 1
- *
- * The first iteration of this loop determines a reflection G
- * from the vector V and applies it from left and right to H,
- * thus creating a nonzero bulge below the subdiagonal.
- *
- * Each subsequent iteration determines a reflection G to
- * restore the Hessenberg form in the (K-1)th column, and thus
- * chases the bulge one step toward the bottom of the active
- * submatrix. NR is the order of G.
- *
- NR = MIN( NS+1, I-K+1 )
- IF( K.GT.L )
- $ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 )
- CALL DLARFG( NR, V( 1 ), V( 2 ), 1, TAU )
- IF( K.GT.L ) THEN
- H( K, K-1 ) = V( 1 )
- DO 130 II = K + 1, I
- H( II, K-1 ) = ZERO
- 130 CONTINUE
- END IF
- V( 1 ) = ONE
- *
- * Apply G from the left to transform the rows of the matrix in
- * columns K to I2.
- *
- CALL DLARFX( 'Left', NR, I2-K+1, V, TAU, H( K, K ), LDH,
- $ WORK )
- *
- * Apply G from the right to transform the columns of the
- * matrix in rows I1 to min(K+NR,I).
- *
- CALL DLARFX( 'Right', MIN( K+NR, I )-I1+1, NR, V, TAU,
- $ H( I1, K ), LDH, WORK )
- *
- IF( WANTZ ) THEN
- *
- * Accumulate transformations in the matrix Z
- *
- CALL DLARFX( 'Right', NH, NR, V, TAU, Z( ILO, K ), LDZ,
- $ WORK )
- END IF
- 140 CONTINUE
- *
- 150 CONTINUE
- *
- * Failure to converge in remaining number of iterations
- *
- INFO = I
- RETURN
- *
- 160 CONTINUE
- *
- * A submatrix of order <= MAXB in rows and columns L to I has split
- * off. Use the double-shift QR algorithm to handle it.
- *
- CALL DLAHQR( WANTT, WANTZ, N, L, I, H, LDH, WR, WI, ILO, IHI, Z,
- $ LDZ, INFO )
- IF( INFO.GT.0 )
- $ RETURN
- *
- * Decrement number of remaining iterations, and return to start of
- * the main loop with a new value of I.
- *
- ITN = ITN - ITS
- I = L - 1
- GO TO 50
- *
- 170 CONTINUE
- RETURN
- *
- * End of DHSEQR
- *
- END
-